package cn.hznc.controller.service.codescanner;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hznc.controller.service.inventory.ToolPartService;
import cn.hznc.controller.service.inventory.ToolPartsInventoryService;
import cn.hznc.domain.entity.*;
import cn.hznc.domain.request.codescanner.*;
import cn.hznc.exception.ToolLifeCycleEx;
import cn.hznc.exception.ToolLifeCycleException;
import cn.hznc.exception.ToolManageEx;
import cn.hznc.exception.ToolManageException;
import cn.hznc.mapper.*;
import cn.hznc.repository.ToolPartRespository;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Author：Administrator
 * @Date：2023/7/26 11:23
 */
@Service
@EnableConfigurationProperties(CodeScannerProp.class)
public class CodeScannerService{

    @Resource
    private CodeScannerMapper codeScannerMapper;

    @Resource
    private ToolPartService toolPartService;

    @Resource
    private AssemblyToolInventoryMapper assemblyToolInventoryMapper;

    @Resource
    private ToolForkInfoMapper toolForkInfoMapper;

    @Resource
    private CodeScannerProp codeScannerProp;

    @Resource
    private CodeScannerUrlMapper codeScannerUrlMapper;

    @Resource
    private ToolPartRespository toolPartRespository;

    @Resource
    private ToolPartsInventoryService toolPartsInventoryService;

    private static final String CONNECT_URL = "/Modbus/Open/RTU";

    private static final String READ_WRITE_URL = "/Modbus/Function";

    public Object editConfiguration(EditConfigurationReq editConfigurationReq){
        QueryWrapper<CodeScannerConfigureEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("operate_type" , editConfigurationReq.getOperateType());
        codeScannerMapper.delete(wrapper);
        //新增
        List<SingleEditConfigurationReq> editConfigurationReqs = editConfigurationReq.getEditConfigurationReqs();
        List<CodeScannerConfigureEntity> insertList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(editConfigurationReqs)){
            editConfigurationReqs.forEach(singleEditConfigurationReq -> {
                    //新增
                    CodeScannerConfigureEntity codeScannerConfigureEntity = new CodeScannerConfigureEntity();
                    BeanUtil.copyProperties(singleEditConfigurationReq , codeScannerConfigureEntity);
                    codeScannerConfigureEntity.setId(null);
                    insertList.add(codeScannerConfigureEntity);
            });
        }
        codeScannerMapper.insertBatchSomeColumn(insertList);
        return Boolean.TRUE;
    }

    public Object editAddressConfiguration(String address) {
        List<CodeScannerConfigureEntity> codeScannerConfigureEntities = codeScannerMapper.selectList(new QueryWrapper<>());
        if(CollectionUtil.isNotEmpty(codeScannerConfigureEntities)){
            codeScannerConfigureEntities.forEach(codeScannerConfigureEntity -> codeScannerConfigureEntity.setAddress(address));
            codeScannerMapper.updateBatchById(codeScannerConfigureEntities);
        }
        return Boolean.TRUE;
    }

    public Object deleteConfiguration(Integer id) {
        if(ObjectUtil.isNotNull(id)){
            codeScannerMapper.deleteById(id);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public Object qryConfiguration( String operateType) {
        QueryWrapper<CodeScannerConfigureEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("operate_type" , operateType);
        return codeScannerMapper.selectList(wrapper);
    }

    public Object qryAddressConfiguration() {
        List<CodeScannerConfigureEntity> selectList = codeScannerMapper.selectList(new QueryWrapper<>());
        if(CollectionUtil.isNotEmpty(selectList)){
            return selectList.get(0).getAddress();
        }
        return "";
    }

    public String getConnectId(String address , String url) {
        if(StringUtil.isEmpty(address)){
            return "";
        }
        Map<String , Object> paramMap = new HashMap<>();
        paramMap.put("address",address);
        paramMap.put("baudRate",115200);
        paramMap.put("dataBits",8);
        paramMap.put("stopBits",1);
        paramMap.put("parity","N");
        paramMap.put("slaveId",2);
        paramMap.put("timeout",5);
        String post = HttpUtil.post(url+CONNECT_URL, paramMap);
        if(StringUtil.isNotEmpty(post)){
            JSONObject jsonObject = JSONObject.parseObject(post);
            JSONObject data = JSONObject.parseObject(jsonObject.get("data").toString());
            if(data.get("success").equals(true)){
                Object connectionId = data.get("connectionId");
                return connectionId.toString();
            }
            return "";
        }
        return "";
    }

//    public Object readUniqueId(CodeScannerConfigureEntity codeScannerConfigureEntity) throws ToolManageException {
//        if(StringUtil.isEmpty(codeScannerConfigureEntity.getAddress())){
//            throw new ToolManageException(ToolManageEx.ADDRESS_EMPTY.getCode() , ToolManageEx.ADDRESS_EMPTY.getMsg());
//        }
//        if(ObjectUtil.isNull(codeScannerConfigureEntity.getStartBit())){
//            throw new ToolManageException(ToolManageEx.START_BIT_EMPTY.getCode() , ToolManageEx.START_BIT_EMPTY.getMsg());
//        }
//        if(ObjectUtil.isNull(codeScannerConfigureEntity.getOffset())){
//            throw new ToolManageException(ToolManageEx.OFFSET_EMPTY.getCode() , ToolManageEx.OFFSET_EMPTY.getMsg());
//        }
//        String connectId = getConnectId(codeScannerConfigureEntity.getAddress());
//        if(StringUtil.isNotEmpty(connectId)){
//            Map<String , Object> paramMap = new HashMap<>();
//            paramMap.put("connectionId" , connectId);
//            paramMap.put("functionCode" , 3);
//            paramMap.put("address" , codeScannerConfigureEntity.getStartBit());
//            paramMap.put("quantity" , codeScannerConfigureEntity.getOffset());
//            String post = HttpUtil.post("http://localhost:33123/Modbus/Function", paramMap);
//            JSONObject jsonObject = JSONObject.parseObject(post);
//            JSONObject data = JSONObject.parseObject(jsonObject.get("data").toString());
//            StringBuilder uniqueIdSb = new StringBuilder();
//            if(data.get("success").equals(true)){
//                JSONArray jsonArray = JSONArray.parseArray(data.get("value").toString());
//                for (Object o : jsonArray) {
//                    if ((int) o != 0) {
//                        char c = (char) (int) o;
//                        uniqueIdSb.append(c);
//                    }
//                }
//            }
//            return uniqueIdSb.toString();
//        }
//        return "";
//    }

    public String readSingleParam(CodeScannerConfigureEntity codeScannerConfigureEntity , String url , String com) throws ToolManageException {
        if(StringUtil.isEmpty(codeScannerConfigureEntity.getAddress())){
            throw new ToolManageException(ToolManageEx.ADDRESS_EMPTY.getCode() , ToolManageEx.ADDRESS_EMPTY.getMsg());
        }
        if(ObjectUtil.isNull(codeScannerConfigureEntity.getStartBit())){
            throw new ToolManageException(ToolManageEx.START_BIT_EMPTY.getCode() , ToolManageEx.START_BIT_EMPTY.getMsg());
        }
        if(ObjectUtil.isNull(codeScannerConfigureEntity.getOffset())){
            throw new ToolManageException(ToolManageEx.OFFSET_EMPTY.getCode() , ToolManageEx.OFFSET_EMPTY.getMsg());
        }
        String connectId = getConnectId(com , url);
        if(StringUtil.isNotEmpty(connectId)){
            Map<String , Object> paramMap = new HashMap<>();
            paramMap.put("connectionId" , connectId);
            paramMap.put("functionCode" , 3);
            paramMap.put("address" , codeScannerConfigureEntity.getStartBit());
            paramMap.put("quantity" , codeScannerConfigureEntity.getOffset());
            String post = HttpUtil.post(url+READ_WRITE_URL, paramMap);
            JSONObject jsonObject = JSONObject.parseObject(post);
            JSONObject data = JSONObject.parseObject(jsonObject.get("data").toString());
            StringBuilder uniqueIdSb = new StringBuilder();
            if(data.get("success").equals(true)){
                JSONArray jsonArray = JSONArray.parseArray(data.get("value").toString());
                for (Object o : jsonArray) {
                    if ((int) o != 0) {
                        char c = (char) (int) o;
                        uniqueIdSb.append(c);
                    }
                }
            }
            return uniqueIdSb.toString();
        }
        return "";
    }

//    public Object writeUniqueId(WriteUniqueIdReq writeUniqueIdReq) throws ToolManageException {
//        CodeScannerConfigureEntity codeScannerConfigureEntity = writeUniqueIdReq.getCodeScannerConfigureEntity();
//        if(StringUtil.isEmpty(codeScannerConfigureEntity.getAddress())){
//            throw new ToolManageException(ToolManageEx.ADDRESS_EMPTY.getCode() , ToolManageEx.ADDRESS_EMPTY.getMsg());
//        }
//        if(ObjectUtil.isNull(codeScannerConfigureEntity.getStartBit())){
//            throw new ToolManageException(ToolManageEx.START_BIT_EMPTY.getCode() , ToolManageEx.START_BIT_EMPTY.getMsg());
//        }
//        if(ObjectUtil.isNull(codeScannerConfigureEntity.getOffset())){
//            throw new ToolManageException(ToolManageEx.OFFSET_EMPTY.getCode() , ToolManageEx.OFFSET_EMPTY.getMsg());
//        }
//        String connectId = getConnectId(codeScannerConfigureEntity.getAddress());
//        if(StringUtil.isNotEmpty(connectId)){
//            String uniqueId = writeUniqueIdReq.getUniqueId();
//            Map<String , Object> paramMap = new HashMap<>();
//            paramMap.put("connectionId" , connectId);
//            paramMap.put("functionCode" , 16);
//            paramMap.put("address" , codeScannerConfigureEntity.getStartBit());
//            paramMap.put("quantity" , codeScannerConfigureEntity.getOffset());
//            List<Integer> numList = new ArrayList<>();
//            for (int i = 0; i < uniqueId.length(); i++) {
//                int ascIINum = (int)uniqueId.charAt(i);
//                numList.add(ascIINum);
//            }
//            paramMap.put("values" , numList);
//            String post = HttpUtil.post("http://localhost:33123/Modbus/Function", JSONObject.toJSONString(paramMap));
//            JSONObject jsonObject = JSONObject.parseObject(post);
//            JSONObject data = JSONObject.parseObject(jsonObject.get("data").toString());
//            if(data.get("success").equals(true)){
//                return Boolean.TRUE;
//            }
//        }
//        return Boolean.FALSE;
//    }

    public Boolean writeSingleParam(CodeScannerConfigureEntity codeScannerConfigureEntity , String value , String url , String com) throws ToolManageException{
        if(StringUtil.isEmpty(codeScannerConfigureEntity.getAddress())){
            throw new ToolManageException(ToolManageEx.ADDRESS_EMPTY.getCode() , ToolManageEx.ADDRESS_EMPTY.getMsg());
        }
        if(ObjectUtil.isNull(codeScannerConfigureEntity.getStartBit())){
            throw new ToolManageException(ToolManageEx.START_BIT_EMPTY.getCode() , ToolManageEx.START_BIT_EMPTY.getMsg());
        }
        if(ObjectUtil.isNull(codeScannerConfigureEntity.getOffset())){
            throw new ToolManageException(ToolManageEx.OFFSET_EMPTY.getCode() , ToolManageEx.OFFSET_EMPTY.getMsg());
        }
        String connectId = getConnectId(com , url);
        if(StringUtil.isNotEmpty(connectId)){
            Map<String , Object> paramMap = new HashMap<>();
            paramMap.put("connectionId" , connectId);
            paramMap.put("functionCode" , 16);
            paramMap.put("address" , codeScannerConfigureEntity.getStartBit());
            List<Integer> numList = new ArrayList<>();
            if(StringUtil.isEmpty(value)){
                value = "0";
            }
            for (int i = 0; i < value.length(); i++) {
                int ascIINum = (int)value.charAt(i);
                numList.add(ascIINum);
            }
            for (int i = 0; i < codeScannerConfigureEntity.getOffset() - value.length(); i++) {
                numList.add(0);
            }
            paramMap.put("quantity" , codeScannerConfigureEntity.getOffset());
            paramMap.put("values" , numList);
            String post = HttpUtil.post(url +READ_WRITE_URL, JSONObject.toJSONString(paramMap));
            JSONObject jsonObject = JSONObject.parseObject(post);
            JSONObject data = JSONObject.parseObject(jsonObject.get("data").toString());
            if(data.get("success").equals(true)){
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 底层方法（输入值写入）
     * @param writeParamsReq
     * @return
     * @throws ToolManageException
     */
    public Boolean writeParams(WriteParamsReq writeParamsReq) throws ToolManageException{
        List<SingleParamReq> writeParams = writeParamsReq.getWriteParams();
        if(CollectionUtil.isNotEmpty(writeParams)){
            for (int i = 0; i < writeParams.size(); i++) {
                QueryWrapper<CodeScannerConfigureEntity> wrapper = new QueryWrapper<>();
                wrapper.eq("operate_type" , writeParamsReq.getOperateType());
                wrapper.eq("type_name" , writeParams.get(i).getParam());
                CodeScannerConfigureEntity codeScannerConfigureEntity = codeScannerMapper.selectOne(wrapper);
                if(!writeSingleParam(codeScannerConfigureEntity , writeParams.get(i).getValue() , writeParamsReq.getUrl() , writeParamsReq.getCom())){
                 return Boolean.FALSE;
                }
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 重载方法（转换输入值（物料编码、刀号转换唯一标识））
     * @param writeParamsReq
     * @return
     * @throws ToolManageException
     */
    public Object writeParamsReload(WriteParamsReq writeParamsReq) throws ToolManageException , ToolLifeCycleException {
        List<SingleParamReq> writeParams = writeParamsReq.getWriteParams();
        for (int i = 0; i < writeParams.size(); i++) {
            SingleParamReq singleParamReq = writeParams.get(i);
            if(singleParamReq.getParam().equals("物料编码")){
                singleParamReq.setValue(generateToolUniqueIdByPartno(singleParamReq.getValue()));
            }else if(singleParamReq.getParam().equals("刀具号")){
                singleParamReq.setValue(generateAssemblyToolUniqueIdByToolNo(singleParamReq.getValue()));
            }
        }
        writeParams(writeParamsReq);
        return Boolean.TRUE;
    }

    public String generateAssemblyToolUniqueIdByToolNo(String toolNo) throws ToolLifeCycleException {
        QueryWrapper<AssemblyToolInventoryEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("tool_no" , toolNo);
        AssemblyToolInventoryEntity assemblyToolInventoryEntity = assemblyToolInventoryMapper.selectOne(wrapper);
        if(ObjectUtil.isNull(assemblyToolInventoryEntity)){
            throw new ToolLifeCycleException(ToolLifeCycleEx.ASSEMBLY_TOOL_TYPE_NO_EXIT.getCode(), ToolLifeCycleEx.ASSEMBLY_TOOL_TYPE_NO_EXIT.getMsg());
        }
        return toolPartService.generateToolUniqueIdPrefix(assemblyToolInventoryEntity.getType())+"."+assemblyToolInventoryEntity.getToolNo() + "." + toolPartService.generateTimeCode()+"."+UUID.randomUUID().toString().replaceAll("-", "").substring(0,5);
    }

    public String generateToolUniqueIdByPartno(String partno) throws ToolLifeCycleException {
        QueryWrapper<ToolForkInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("partno" , partno);
        ToolForkInfoEntity toolForkInfoEntity = toolForkInfoMapper.selectOne(wrapper);
        if(ObjectUtil.isNull(toolForkInfoEntity)){
            throw new ToolLifeCycleException(ToolLifeCycleEx.TOOL_NO_EXIST.getCode() , ToolLifeCycleEx.TOOL_NO_EXIST.getMsg());
        }
        return toolPartService.generateToolUniqueIdPrefix(toolForkInfoEntity.getType()) + "."+ toolForkInfoEntity.getPartno()+"."+toolPartService.generateTimeCode()+"." + UUID.randomUUID().toString().replaceAll("-", "").substring(0,5);
    }

    public Map<String , String> readParams(String operateType , String url , String com) throws ToolManageException {
        Map<String , String> retMap = new HashMap<>();
        QueryWrapper<CodeScannerConfigureEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("operate_Type" , operateType);
        List<CodeScannerConfigureEntity> readConfigurations = codeScannerMapper.selectList(wrapper);
        if(CollectionUtil.isNotEmpty(readConfigurations)){
            for (int i = 0; i < readConfigurations.size(); i++) {
                CodeScannerConfigureEntity codeScannerConfigureEntity = readConfigurations.get(i);
                if(codeScannerConfigureEntity.getTypeName().equals("物料编码")||codeScannerConfigureEntity.getTypeName().equals("刀具号")){
                    retMap.put("uniqueId" , readSingleParam(codeScannerConfigureEntity , url , com));
                }else if(codeScannerConfigureEntity.getTypeName().equals("额定寿命")){
                    retMap.put("life" , readSingleParam(codeScannerConfigureEntity , url , com));
                }else if(codeScannerConfigureEntity.getTypeName().equals("长度")){
                    retMap.put("length" , readSingleParam(codeScannerConfigureEntity , url , com));
                }else if(codeScannerConfigureEntity.getTypeName().equals("半径")){
                    retMap.put("radius" , readSingleParam(codeScannerConfigureEntity , url , com));
                }else if(codeScannerConfigureEntity.getTypeName().equals("刀柄RFID")){
                    retMap.put("shankRfid" , readSingleParam(codeScannerConfigureEntity , url , com));
                    ToolPartEntity uniqueId = toolPartRespository.getByUniqueId(retMap.get("shankRfid"));
                    if(ObjectUtil.isNotNull(uniqueId) && ObjectUtil.isNotNull(uniqueId.getId()) && ObjectUtil.isNotNull(uniqueId.getInventoryLocationId())){
                        retMap.put("warehousesName" , toolPartsInventoryService.buildLocationName(uniqueId.getInventoryLocationId()));
                    }else {
                        retMap.put("warehousesName" , "");
                    }
                }else if(codeScannerConfigureEntity.getTypeName().equals("刀柄型号")){
                    retMap.put("shankType" , readSingleParam(codeScannerConfigureEntity , url , com));
                }else if(codeScannerConfigureEntity.getTypeName().equals("刀柄物料编码")){
                    retMap.put("shankPartno" , readSingleParam(codeScannerConfigureEntity , url , com));
                }

            }
        }
        return retMap;
    }

    public Object addOrEditUrl(CodeScannerEntity codeScannerEntity) {
        if(ObjectUtil.isNotNull(codeScannerEntity.getId())){
            //修改
            codeScannerUrlMapper.updateById(codeScannerEntity);
            return Boolean.TRUE;
        }
        codeScannerUrlMapper.insert(codeScannerEntity);
        return Boolean.TRUE;
    }

    public Object selectCodeScannerUrls() {
        return codeScannerUrlMapper.selectList(new QueryWrapper<>());
    }

    public Object deleteCodeScannerUrl(Integer id) {
        codeScannerUrlMapper.deleteById(id);
        return Boolean.TRUE;
    }

    public Object writeShankParam(WriteShankParamReq writeShankParamReq) throws ToolLifeCycleException, ToolManageException {
        if(StringUtil.isEmpty(writeShankParamReq.getUniqueId())){
            throw new ToolLifeCycleException(ToolLifeCycleEx.TOOL_UNIQUE_ID_NO_EXIST.getCode(), ToolLifeCycleEx.TOOL_UNIQUE_ID_NO_EXIST.getMsg());
        }
        if(writeParams(writeShankParamReq)){
            toolPartRespository.updateByRfid(writeShankParamReq.getUniqueId());
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}
